library ieee;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_unsigned.all;

library work;
    use work.router_pack.all;


-------------------------------------------------------------------------------
entity tb_msl_router is
-------------------------------------------------------------------------------
-- empty
-------------------------------------------------------------------------------
end tb_msl_router ;
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
architecture tb_msl_router_arch of tb_msl_router is
-------------------------------------------------------------------------------

component msl_router
port(
       -- General Signlas: --
       RESET           : in  std_logic; 
       
       -- Input Ports i/f: --
       RI              : in  std_logic_vector(num_of_ports_con downto 0);
       AI              : out std_logic_vector(num_of_ports_con downto 0);
       DI              : in  msl_router_mult_ports_data_bus_type;
       
       -- Output Ports i/f: --
       RO              : out std_logic_vector(num_of_ports_con downto 0);
       AO              : in  std_logic_vector(num_of_ports_con downto 0);
       DO              : out msl_router_mult_ports_data_bus_type
    );  
end component;

signal       RESET           :   std_logic; 
       
signal       RI              :   std_logic_vector(num_of_ports_con downto 0);
signal       AI              :   std_logic_vector(num_of_ports_con downto 0);
signal       DI              :   msl_router_mult_ports_data_bus_type;
       
signal       RO              :   std_logic_vector(num_of_ports_con downto 0);
signal       AO              :   std_logic_vector(num_of_ports_con downto 0);
signal       DO              :   msl_router_mult_ports_data_bus_type;

signal clk : std_logic := '0';
signal cnt : integer;

begin 

u_msl_router: msl_router
port map(
       RESET           => RESET, 
       
       RI              => RI,
       AI              => AI,
       DI              => DI,
       
       RO              => RO,
       AO              => AO,
       DO              => DO
);  

AO <= RO after 20 ns; -- automatic acknowelwedge.

clk_proc: process(RESET, clk)
begin
 if (RESET = '1' ) then
  RI <= (others=>'0');
  DI <= (others=>(others=>'0'));

  cnt <= 0;

 elsif ( clk'event and clk='1' ) then
  cnt <= cnt + 1;

  -- End of protocol for input: --
  if ( AI(1) = '1' ) then
     RI(1) <= '0';
  end if;
  if ( AI(2) = '1' ) then
     RI(2) <= '0';
  end if;

  -- The testbench currently performs the following operations: --
  -- a. Begins with concurrent sending of three packets from ports 0,1,2 (same SL)
  --  to the same OP (4).
  -- b. The first packets (from IP=0) constains three flits: h, b, t.
  --    The other two packets have only two flits: h, t.
  -- c. The first two packets catch two VC and the third packet is stuck. 
  -- d. When the long packet is finished, another long packet (of three is sent to IP=0) and is 
  --    also stuck because the third packet catches the released output VC.
  -- e. When one of the VCs is released the last (fourth) packet goes through the router.
  -- f. Total: 3 + 2 + 2 + 3 = 10 flits and 4 packets are sent.
  
  case cnt is
   when 9 =>
     DI(0) <= "0010111111111";  --  VC=0, Sl=1, Header, Addr=11 (to OP=4)
     
     -- Additional two packet requests: --
     DI(1) <= "0010111010101";  --  VC=0, Sl=1, Header, Addr=11 (to OP=4)
     DI(2) <= "0010111010101";  --  VC=0, Sl=1, Header, Addr=11 (to OP=4)

   when 10 =>
     RI(0) <= '1';

     -- Additional two concurrent packet requests: --
     RI(1) <= '1';
     RI(2) <= '1';

   when 11 =>
     if ( AI(0) = '1' ) then
       RI(0) <= '0';
     else
       cnt <= cnt; -- wait here.
     end if;


   when 12 =>
     if ( AI(0) = '0' ) then
       cnt <= cnt + 1;
     else
       cnt <= cnt; -- wait here.
     end if;
----------------------------
   when 13 =>
     DI(0) <= "0010011111111";  -- VC=0, Sl=1, Body
     
   when 14 =>
     RI(0) <= '1';

   when 15 =>
     if ( AI(0) = '1' ) then
       RI(0) <= '0';
     else
       cnt <= cnt; -- wait here.
     end if;
  
   when 16 =>
     if ( AI(0) = '0' ) then
       cnt <= cnt + 1;
     else
       cnt <= cnt; -- wait here.
     end if;

----------------------------
   when 17 =>
     DI(0) <= "0011011111111";  -- VC=0, Sl=1, Tail
     
   when 18 =>
     RI(0) <= '1';

   when 19 =>
     if ( AI(0) = '1' ) then
       RI(0) <= '0';
     else
       cnt <= cnt; -- wait here.
     end if;
  
   when 20 =>
     if ( AI(0) = '0' ) then
       cnt <= cnt + 1;
     else
       cnt <= cnt; -- wait here.
     end if;

-----------------------------------------
--- Second packet to port0: --
   when 25 =>
     DI(0) <= "0010111111111";  --  VC=0, Sl=1, Header, Addr=11 (to OP=4)
     -- EOP to port1 and port2
     DI(1) <= "0011011010111";  --  Port1, VC=0, Sl=1, Tail, Addr=11 (to OP=4)
     DI(2) <= "0011011010101";  --  Port2, VC=0, Sl=1, Tail, Addr=11 (to OP=4)     

   when 26 =>
     RI(0) <= '1';

   --- port1/2  
   when 27 =>
     RI(1) <= '1';
     RI(2) <= '1';

   when 28 =>
     if ( AI(1) = '1' and AI(2) = '1' ) then
       RI(1) <= '0';
       RI(2) <= '0';
     else
       cnt <= cnt; -- wait here.
     end if;
  
   when 29 =>
     if ( AI(1) = '0' and AI(2) = '0' ) then
       cnt <= cnt + 1;
     else
       cnt <= cnt; -- wait here.
     end if;
   --- port1/2  

   when 30 =>
     if ( AI(0) = '1' ) then
       RI(0) <= '0';
     else
       cnt <= cnt; -- wait here.
     end if;

   when 31 =>
     if ( AI(0) = '0' ) then
       cnt <= cnt + 1;
     else
       cnt <= cnt; -- wait here.
     end if;
----------------------------
   when 32 =>
     DI(0) <= "0010011111111";  -- VC=0, Sl=1, Body
     
   when 33 =>
     RI(0) <= '1';

   when 34 =>
     if ( AI(0) = '1' ) then
       RI(0) <= '0';
     else
       cnt <= cnt; -- wait here.
     end if;
  
   when 35 =>
     if ( AI(0) = '0' ) then
       cnt <= cnt + 1;
     else
       cnt <= cnt; -- wait here.
     end if;

----------------------------
   when 36 =>
     DI(0) <= "0011011111111";  -- VC=0, Sl=1, Tail
     
   when 37 =>
     RI(0) <= '1';

   when 38 =>
     if ( AI(0) = '1' ) then
       RI(0) <= '0';
     else
       cnt <= cnt; -- wait here.
     end if;
  
   when 39 =>
     if ( AI(0) = '0' ) then
       cnt <= cnt + 1;
     else
       cnt <= cnt; -- wait here.
     end if;

   when others=> NULL;
  end case;

 end if;
end process;

RESET <= '1', '0' after 200 ns;
clk <= not clk after 10 ns;

-------------------------------------------------------------------------------
end tb_msl_router_arch;
-------------------------------------------------------------------------------                 

   
-------------------------------------------------------------------------------
configuration  tb_msl_router_cfg  of tb_msl_router is
-------------------------------------------------------------------------------
   for tb_msl_router_arch
   end for;
-------------------------------------------------------------------------------
end  tb_msl_router_cfg;              
-------------------------------------------------------------------------------
                 
